home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Modules / imgfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-03  |  11.1 KB  |  539 lines

  1. /* IMGFILE module - Interface to sgi libimage */
  2.  
  3. /* XXX This modele should be done better at some point. It should return
  4. ** an object of image file class, and have routines to manipulate these
  5. ** image files in a neater way (so you can get rgb images off a greyscale
  6. ** file, for instance, or do a straight display without having to get the
  7. ** image bits into python, etc).
  8. **
  9. ** Warning: this module is very non-reentrant (esp. the readscaled stuff)
  10. */
  11.  
  12. #include "Python.h"
  13.  
  14. #include <gl/image.h>
  15.  
  16. #include "/usr/people/4Dgifts/iristools/include/izoom.h"
  17.  
  18. /* Bunch of missing extern decls; keep gcc -Wall happy... */
  19. extern void i_seterror();
  20. extern void iclose();
  21. extern void filterzoom();
  22. extern void putrow();
  23. extern void getrow();
  24.  
  25. static PyObject * ImgfileError; /* Exception we raise for various trouble */
  26.  
  27. static int top_to_bottom;    /* True if we want top-to-bottom images */
  28.  
  29. /* The image library does not always call the error hander :-(,
  30.    therefore we have a global variable indicating that it was called.
  31.    It is cleared by imgfile_open(). */
  32.  
  33. static int error_called;
  34.  
  35.  
  36. /* The error handler */
  37.  
  38. static void
  39. imgfile_error(str)
  40.     char *str;
  41. {
  42.     PyErr_SetString(ImgfileError, str);
  43.     error_called = 1;
  44.     return;    /* To imglib, which will return a failure indicator */
  45. }
  46.  
  47.  
  48. /* Open an image file and return a pointer to it.
  49.    Make sure we raise an exception if we fail. */
  50.  
  51. static IMAGE *
  52. imgfile_open(fname)
  53.     char *fname;
  54. {
  55.     IMAGE *image;
  56.     i_seterror(imgfile_error);
  57.     error_called = 0;
  58.     errno = 0;
  59.     if ( (image = iopen(fname, "r")) == NULL ) {
  60.         /* Error may already be set by imgfile_error */
  61.         if ( !error_called ) {
  62.             if (errno)
  63.                 PyErr_SetFromErrno(ImgfileError);
  64.             else
  65.                 PyErr_SetString(ImgfileError,
  66.                         "Can't open image file");
  67.         }
  68.         return NULL;
  69.     }
  70.     return image;
  71. }
  72.  
  73. static PyObject *
  74. imgfile_ttob(self, args)
  75.     PyObject *self;
  76. PyObject *args;
  77. {
  78.     int newval;
  79.     PyObject *rv;
  80.     
  81.     if (!PyArg_Parse(args, "i", &newval))
  82.         return NULL;
  83.     rv = PyInt_FromLong(top_to_bottom);
  84.     top_to_bottom = newval;
  85.     return rv;
  86. }
  87.  
  88. static PyObject *
  89. imgfile_read(self, args)
  90.     PyObject *self;
  91. PyObject *args;
  92. {
  93.     char *fname;
  94.     PyObject *rv;
  95.     int xsize, ysize, zsize;
  96.     char *cdatap;
  97.     long *idatap;
  98.     static short rs[8192], gs[8192], bs[8192];
  99.     int x, y;
  100.     IMAGE *image;
  101.     int yfirst, ylast, ystep;
  102.  
  103.     if ( !PyArg_Parse(args, "s", &fname) )
  104.         return NULL;
  105.     
  106.     if ( (image = imgfile_open(fname)) == NULL )
  107.         return NULL;
  108.     
  109.     if ( image->colormap != CM_NORMAL ) {
  110.         iclose(image);
  111.         PyErr_SetString(ImgfileError,
  112.                 "Can only handle CM_NORMAL images");
  113.         return NULL;
  114.     }
  115.     if ( BPP(image->type) != 1 ) {
  116.         iclose(image);
  117.         PyErr_SetString(ImgfileError,
  118.                 "Can't handle imgfiles with bpp!=1");
  119.         return NULL;
  120.     }
  121.     xsize = image->xsize;
  122.     ysize = image->ysize;
  123.     zsize = image->zsize;
  124.     if ( zsize != 1 && zsize != 3) {
  125.         iclose(image);
  126.         PyErr_SetString(ImgfileError,
  127.                 "Can only handle 1 or 3 byte pixels");
  128.         return NULL;
  129.     }
  130.     if ( xsize > 8192 ) {
  131.         iclose(image);
  132.         PyErr_SetString(ImgfileError,
  133.                 "Can't handle image with > 8192 columns");
  134.         return NULL;
  135.     }
  136.  
  137.     if ( zsize == 3 ) zsize = 4;
  138.     rv = PyString_FromStringAndSize((char *)NULL, xsize*ysize*zsize);
  139.     if ( rv == NULL ) {
  140.         iclose(image);
  141.         return NULL;
  142.     }
  143.     cdatap = PyString_AsString(rv);
  144.     idatap = (long *)cdatap;
  145.  
  146.     if (top_to_bottom) {
  147.         yfirst = ysize-1;
  148.         ylast = -1;
  149.         ystep = -1;
  150.     } else {
  151.         yfirst = 0;
  152.         ylast = ysize;
  153.         ystep = 1;
  154.     }
  155.     for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
  156.         if ( zsize == 1 ) {
  157.             getrow(image, rs, y, 0);
  158.             for(x=0; x<xsize; x++ )
  159.                 *cdatap++ = rs[x];
  160.         } else {
  161.             getrow(image, rs, y, 0);
  162.             getrow(image, gs, y, 1);
  163.             getrow(image, bs, y, 2);
  164.             for(x=0; x<xsize; x++ )
  165.                 *idatap++ = (rs[x] & 0xff)  |
  166.                     ((gs[x] & 0xff)<<8) |
  167.                     ((bs[x] & 0xff)<<16);
  168.         }
  169.     }
  170.     iclose(image);
  171.     if ( error_called ) {
  172.         Py_DECREF(rv);
  173.         return NULL;
  174.     }
  175.     return rv;
  176. }
  177.  
  178. static IMAGE *glob_image;
  179. static long *glob_datap;
  180. static int glob_width, glob_z, glob_ysize;
  181.  
  182. static void
  183. xs_get(buf, y)
  184.     short *buf;
  185. int y;
  186. {
  187.     if (top_to_bottom)
  188.         getrow(glob_image, buf, (glob_ysize-1-y), glob_z);
  189.     else
  190.         getrow(glob_image, buf, y, glob_z);
  191. }
  192.  
  193. static void
  194. xs_put_c(buf, y)
  195.     short *buf;
  196. int y;
  197. {
  198.     char *datap = (char *)glob_datap + y*glob_width;
  199.     int width = glob_width;
  200.  
  201.     while ( width-- )
  202.         *datap++ = (*buf++) & 0xff;
  203. }
  204.  
  205. static void
  206. xs_put_0(buf, y)
  207.     short *buf;
  208. int y;
  209. {
  210.     long *datap = glob_datap + y*glob_width;
  211.     int width = glob_width;
  212.  
  213.     while ( width-- )
  214.         *datap++ = (*buf++) & 0xff;
  215. }
  216. static void
  217. xs_put_12(buf, y)
  218.     short *buf;
  219. int y;
  220. {
  221.     long *datap = glob_datap + y*glob_width;
  222.     int width = glob_width;
  223.  
  224.     while ( width-- )
  225.         *datap++ |= ((*buf++) & 0xff) << (glob_z*8);
  226. }
  227.  
  228. static void
  229. xscale(image, xsize, ysize, zsize, datap, xnew, ynew, fmode, blur)
  230.     IMAGE *image;
  231. int xsize, ysize, zsize;
  232. long *datap;
  233. int xnew, ynew;
  234. int fmode;
  235. double blur;
  236. {
  237.     glob_image = image;
  238.     glob_datap = datap;
  239.     glob_width = xnew;
  240.     glob_ysize = ysize;
  241.     if ( zsize == 1 ) {
  242.         glob_z = 0;
  243.         filterzoom(xs_get, xs_put_c, xsize, ysize,
  244.                xnew, ynew, fmode, blur);
  245.     } else {
  246.         glob_z = 0;
  247.         filterzoom(xs_get, xs_put_0, xsize, ysize,
  248.                xnew, ynew, fmode, blur);
  249.         glob_z = 1;
  250.         filterzoom(xs_get, xs_put_12, xsize, ysize,
  251.                xnew, ynew, fmode, blur);
  252.         glob_z = 2;
  253.         filterzoom(xs_get, xs_put_12, xsize, ysize,
  254.                xnew, ynew, fmode, blur);
  255.     }
  256. }
  257.  
  258.  
  259. static PyObject *
  260. imgfile_readscaled(self, args)
  261.     PyObject *self;
  262. PyObject *args;
  263. {
  264.     char *fname;
  265.     PyObject *rv;
  266.     int xsize, ysize, zsize;
  267.     char *cdatap;
  268.     long *idatap;
  269.     static short rs[8192], gs[8192], bs[8192];
  270.     int x, y;
  271.     int xwtd, ywtd, xorig, yorig;
  272.     float xfac, yfac;
  273.     int cnt;
  274.     IMAGE *image;
  275.     char *filter;
  276.     double blur;
  277.     int extended;
  278.     int fmode = 0;
  279.     int yfirst, ylast, ystep;
  280.  
  281.     /*
  282.     ** Parse args. Funny, since arg 4 and 5 are optional
  283.     ** (filter name and blur factor). Also, 4 or 5 arguments indicates
  284.     ** extended scale algorithm in stead of simple-minded pixel drop/dup.
  285.     */
  286.     extended = 0;
  287.     cnt = PyTuple_Size(args);
  288.     if ( cnt == 5 ) {
  289.         extended = 1;
  290.         if ( !PyArg_Parse(args, "(siisd)",
  291.                   &fname, &xwtd, &ywtd, &filter, &blur) )
  292.             return NULL;
  293.     } else if ( cnt == 4 ) {
  294.         extended = 1;
  295.         if ( !PyArg_Parse(args, "(siis)",
  296.                   &fname, &xwtd, &ywtd, &filter) )
  297.             return NULL;
  298.         blur = 1.0;
  299.     } else if ( !PyArg_Parse(args, "(sii)", &fname, &xwtd, &ywtd) )
  300.         return NULL;
  301.  
  302.     /*
  303.     ** Check parameters, open file and check type, rows, etc.
  304.     */
  305.     if ( extended ) {
  306.         if ( strcmp(filter, "impulse") == 0 )
  307.             fmode = IMPULSE;
  308.         else if ( strcmp( filter, "box") == 0 )
  309.             fmode = BOX;
  310.         else if ( strcmp( filter, "triangle") == 0 )
  311.             fmode = TRIANGLE;
  312.         else if ( strcmp( filter, "quadratic") == 0 )
  313.             fmode = QUADRATIC;
  314.         else if ( strcmp( filter, "gaussian") == 0 )
  315.             fmode = GAUSSIAN;
  316.         else {
  317.             PyErr_SetString(ImgfileError, "Unknown filter type");
  318.             return NULL;
  319.         }
  320.     }
  321.     
  322.     if ( (image = imgfile_open(fname)) == NULL )
  323.         return NULL;
  324.     
  325.     if ( image->colormap != CM_NORMAL ) {
  326.         iclose(image);
  327.         PyErr_SetString(ImgfileError,
  328.                 "Can only handle CM_NORMAL images");
  329.         return NULL;
  330.     }
  331.     if ( BPP(image->type) != 1 ) {
  332.         iclose(image);
  333.         PyErr_SetString(ImgfileError,
  334.                 "Can't handle imgfiles with bpp!=1");
  335.         return NULL;
  336.     }
  337.     xsize = image->xsize;
  338.     ysize = image->ysize;
  339.     zsize = image->zsize;
  340.     if ( zsize != 1 && zsize != 3) {
  341.         iclose(image);
  342.         PyErr_SetString(ImgfileError,
  343.                 "Can only handle 1 or 3 byte pixels");
  344.         return NULL;
  345.     }
  346.     if ( xsize > 8192 ) {
  347.         iclose(image);
  348.         PyErr_SetString(ImgfileError,
  349.                 "Can't handle image with > 8192 columns");
  350.         return NULL;
  351.     }
  352.  
  353.     if ( zsize == 3 ) zsize = 4;
  354.     rv = PyString_FromStringAndSize(NULL, xwtd*ywtd*zsize);
  355.     if ( rv == NULL ) {
  356.         iclose(image);
  357.         return NULL;
  358.     }
  359.     PyFPE_START_PROTECT("readscaled", return 0)
  360.     xfac = (float)xsize/(float)xwtd;
  361.     yfac = (float)ysize/(float)ywtd;
  362.     PyFPE_END_PROTECT(yfac)
  363.     cdatap = PyString_AsString(rv);
  364.     idatap = (long *)cdatap;
  365.  
  366.     if ( extended ) {
  367.         xscale(image, xsize, ysize, zsize,
  368.                idatap, xwtd, ywtd, fmode, blur);
  369.     } else {
  370.         if (top_to_bottom) {
  371.             yfirst = ywtd-1;
  372.             ylast = -1;
  373.             ystep = -1;
  374.         } else {
  375.             yfirst = 0;
  376.             ylast = ywtd;
  377.             ystep = 1;
  378.         }
  379.         for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
  380.             yorig = (int)(y*yfac);
  381.             if ( zsize == 1 ) {
  382.                 getrow(image, rs, yorig, 0);
  383.                 for(x=0; x<xwtd; x++ ) {
  384.                     *cdatap++ = rs[(int)(x*xfac)];    
  385.                 }
  386.             } else {
  387.                 getrow(image, rs, yorig, 0);
  388.                 getrow(image, gs, yorig, 1);
  389.                 getrow(image, bs, yorig, 2);
  390.                 for(x=0; x<xwtd; x++ ) {
  391.                     xorig = (int)(x*xfac);
  392.                     *idatap++ = (rs[xorig] & 0xff)  |
  393.                         ((gs[xorig] & 0xff)<<8) |
  394.                         ((bs[xorig] & 0xff)<<16);
  395.                 }
  396.             }
  397.         }
  398.     }
  399.     iclose(image);
  400.     if ( error_called ) {
  401.         Py_DECREF(rv);
  402.         return NULL;
  403.     }
  404.     return rv;
  405. }
  406.  
  407. static PyObject *
  408. imgfile_getsizes(self, args)
  409.     PyObject *self;
  410. PyObject *args;
  411. {
  412.     char *fname;
  413.     PyObject *rv;
  414.     IMAGE *image;
  415.     
  416.     if ( !PyArg_Parse(args, "s", &fname) )
  417.         return NULL;
  418.     
  419.     if ( (image = imgfile_open(fname)) == NULL )
  420.         return NULL;
  421.     rv = Py_BuildValue("(iii)", image->xsize, image->ysize, image->zsize);
  422.     iclose(image);
  423.     return rv;
  424. }
  425.  
  426. static PyObject *
  427. imgfile_write(self, args)
  428.     PyObject *self;
  429. PyObject *args;
  430. {
  431.     IMAGE *image;
  432.     char *fname;
  433.     int xsize, ysize, zsize, len;
  434.     char *cdatap;
  435.     long *idatap;
  436.     short rs[8192], gs[8192], bs[8192];
  437.     short r, g, b;
  438.     long rgb;
  439.     int x, y;
  440.     int yfirst, ylast, ystep;
  441.  
  442.  
  443.     if ( !PyArg_Parse(args, "(ss#iii)",
  444.               &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
  445.         return NULL;
  446.     
  447.     if ( zsize != 1 && zsize != 3 ) {
  448.         PyErr_SetString(ImgfileError,
  449.                 "Can only handle 1 or 3 byte pixels");
  450.         return NULL;
  451.     }
  452.     if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
  453.         PyErr_SetString(ImgfileError, "Data does not match sizes");
  454.         return NULL;
  455.     }
  456.     if ( xsize > 8192 ) {
  457.         PyErr_SetString(ImgfileError,
  458.                 "Can't handle image with > 8192 columns");
  459.         return NULL;
  460.     }
  461.  
  462.     error_called = 0;
  463.     errno = 0;
  464.     image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
  465.     if ( image == 0 ) {
  466.         if ( ! error_called ) {
  467.             if (errno)
  468.                 PyErr_SetFromErrno(ImgfileError);
  469.             else
  470.                 PyErr_SetString(ImgfileError,
  471.                         "Can't create image file");
  472.         }
  473.         return NULL;
  474.     }
  475.  
  476.     idatap = (long *)cdatap;
  477.     
  478.     if (top_to_bottom) {
  479.         yfirst = ysize-1;
  480.         ylast = -1;
  481.         ystep = -1;
  482.     } else {
  483.         yfirst = 0;
  484.         ylast = ysize;
  485.         ystep = 1;
  486.     }
  487.     for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
  488.         if ( zsize == 1 ) {
  489.             for( x=0; x<xsize; x++ )
  490.                 rs[x] = *cdatap++;
  491.             putrow(image, rs, y, 0);
  492.         } else {
  493.             for( x=0; x<xsize; x++ ) {
  494.                 rgb = *idatap++;
  495.                 r = rgb & 0xff;
  496.                 g = (rgb >> 8 ) & 0xff;
  497.                 b = (rgb >> 16 ) & 0xff;
  498.                 rs[x] = r;
  499.                 gs[x] = g;
  500.                 bs[x] = b;
  501.             }
  502.             putrow(image, rs, y, 0);
  503.             putrow(image, gs, y, 1);
  504.             putrow(image, bs, y, 2);
  505.         }
  506.     }
  507.     iclose(image);
  508.     if ( error_called )
  509.         return NULL;
  510.     Py_INCREF(Py_None);
  511.     return Py_None;
  512.     
  513. }
  514.  
  515.  
  516. static PyMethodDef imgfile_methods[] = {
  517.     { "getsizes",    imgfile_getsizes },
  518.     { "read",    imgfile_read },
  519.     { "readscaled",    imgfile_readscaled, 1},
  520.     { "write",    imgfile_write },
  521.     { "ttob",    imgfile_ttob },
  522.     { NULL,        NULL } /* Sentinel */
  523. };
  524.  
  525.  
  526. void
  527. initimgfile()
  528. {
  529.     PyObject *m, *d;
  530.     m = Py_InitModule("imgfile", imgfile_methods);
  531.     d = PyModule_GetDict(m);
  532.     ImgfileError = PyErr_NewException("imgfile.error", NULL, NULL);
  533.     if (ImgfileError != NULL)
  534.         PyDict_SetItemString(d, "error", ImgfileError);
  535. }
  536.  
  537.  
  538.  
  539.